package com.nsl.my_youlai.bbu2.untils;

import com.nsl.my_youlai.bbu2.enums.NetGenerationEnum;
import com.nsl.my_youlai.bbu2.enums.VendorEnum2;
import com.nsl.my_youlai.bbu2.model.bo.ApparatusRoomBo;
import com.nsl.my_youlai.bbu2.model.bo.bbu.Bbu2;
import com.nsl.my_youlai.bbu2.model.bo.bbu.StringPatternAndBbu;
import com.nsl.my_youlai.bbu2.model.bo.bbu.instances.BbuHw5g5900;
import com.nsl.my_youlai.bbu2.model.bo.bbu.IntPatternAndBbu;
import com.nsl.my_youlai.mystar.NslUtilList;
import com.nsl.my_youlai.mystar.NslUtilPrinter;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class UtilBbuReturn {

    public  static  List<Integer> calCanInjectIntPatternList(Bbu2 bbu){
        //按1frame_1fun_1power_1main_4base考虑
        int targetFrameCounter=0;
        int targetFunCounter=0;
        int targetPowerCounter=0;
        int targetMainCounter=0;
        int targetBaseCounter=0;

        //5g:中兴华为 4基带，1主控，1电源，1机框，1风扇
        //5g:大唐 4基带，1主控，2电源，1机框，1风扇
        //4G: 中兴华为 4基带，1主控，2电源，1机框，1风扇
        if(bbu.getNetGenerationFromBbuModel()== NetGenerationEnum.G4){
            targetFrameCounter=1;
            targetFunCounter=1;
            targetPowerCounter=2;
            targetMainCounter=1;
            targetBaseCounter=4;
        }else{
            if(bbu.getVendor()== VendorEnum2.DA_TANG){
                targetFrameCounter=1;
                targetFunCounter=1;
                targetPowerCounter=2;
                targetMainCounter=1;
                targetBaseCounter=4;
            }else{
                targetFrameCounter=1;
                targetFunCounter=1;
                targetPowerCounter=4;
                targetMainCounter=1;
                targetBaseCounter=4;
            }
        }

        int needFrameCounter=targetFrameCounter-bbu.getFrameCounter();
        int needFunCounter=targetFunCounter-bbu.getFunCounter();
        int needPowerCounter=targetPowerCounter-bbu.getPowerBoardCounter();
        int needMainCounter=targetMainCounter-bbu.getControlBoardCounter();
        int needBaseCounter=targetBaseCounter-bbu.getBaseBoardCounter();
        List<Integer> needPatternList=recycle5Loop(needFrameCounter,needFunCounter,needPowerCounter,needMainCounter,needBaseCounter);
        return  needPatternList;
    }

    /**
     * 计算可插入 板卡形成的组合
     * @param bbu
     * @return
     */
    public  static  List<String> calCanInjectStringPatternList(Bbu2 bbu){
        //按1frame_1fun_1power_1main_4base考虑
        int targetFrameCounter=0;
        int targetFunCounter=0;
        int targetPowerCounter=0;
        int targetMainCounter=0;
        int targetBaseCounter=0;

        //5g:中兴华为 4基带，1主控，1电源，1机框，1风扇
        //5g:大唐 4基带，1主控，1电源，1机框，1风扇 :todo: 目前power 按1走
        //4G: 中兴华为 4基带，1主控，2电源，1机框，1风扇
        if(bbu.getNetGenerationFromBbuModel()== NetGenerationEnum.G4){
            targetFrameCounter=1;
            targetFunCounter=1;
            targetPowerCounter=2;
            targetMainCounter=1;
            targetBaseCounter=4;
        }else{
            if(bbu.getVendor()== VendorEnum2.DA_TANG){
                targetFrameCounter=1;
                targetFunCounter=1;
                targetPowerCounter=1;
                targetMainCounter=1;
                targetBaseCounter=4;
            }else{
                targetFrameCounter=1;
                targetFunCounter=1;
                targetPowerCounter=1;
                targetMainCounter=1;
                targetBaseCounter=4;
            }
        }

        int needFrameCounter=targetFrameCounter-bbu.getFrameCounter();
        int needFunCounter=targetFunCounter-bbu.getFunCounter();
        int needPowerCounter=targetPowerCounter-bbu.getPowerBoardCounter();
        int needMainCounter=targetMainCounter-bbu.getControlBoardCounter();
        int needBaseCounter=targetBaseCounter-bbu.getBaseBoardCounter();
//        log.info("targetPowerCounter={}",targetPowerCounter);
//        log.info("bbu.getPowerBoardCounter()={}",bbu.getPowerBoardCounter());
//        log.info("needPowerCounter={}",needPowerCounter);
//        log.info("needBaseCounter={}",needBaseCounter);
        List<String> needPatternList=recycle5LoopString(needBaseCounter,needMainCounter,needPowerCounter,needFrameCounter,needFunCounter);
        return  needPatternList;
    }

    public static List<StringPatternAndBbu> calCanInjectStringPatternList(List<Bbu2> bbuList){
        List<StringPatternAndBbu> list=new ArrayList<>();
        for (Bbu2 bbu : bbuList) {
            List<String>  bbuPatternStringList=calCanInjectStringPatternList(bbu);
            for (String s : bbuPatternStringList) {
                StringPatternAndBbu stringPatternAndBbu=new StringPatternAndBbu();
                stringPatternAndBbu.setBbu(bbu);
                stringPatternAndBbu.setStringIndex(s);
                list.add(stringPatternAndBbu);
            }
        }
        Iterator<StringPatternAndBbu> it= list.iterator();
        while (it.hasNext()){
            StringPatternAndBbu stringPatternAndBbu=it.next();
            if(stringPatternAndBbu.getStringIndex().equals("0_0_0_0_0")){
                it.remove();
            }
        }
        Collections.sort(list,(bbu1, bbu2)->{
            if(bbu1.getStringIndex()==bbu2.getStringIndex()){
                return bbu1.getBbu().getNodeId()-bbu2.getBbu().getNodeId();
            }else{
                return comparePatternString(bbu2.getStringIndex(),bbu1.getStringIndex());
            }
        });
        return list;
    }



    //用字符串表示pattern
    public static List<Integer> calCanDismentalIntPatternList(Bbu2 bbu){

        //格式：frame_fun_power_main_base
        int frameCounter=bbu.getFrameCounter();
        int funCounter=bbu.getFunCounter();
        int powerCounter=bbu.getPowerBoardCounter();
        int mainCounter=bbu.getControlBoardCounter();
        int baseCounter=bbu.getBaseBoardCounter();
        List<Integer> patternList=recycle5Loop(frameCounter,funCounter,powerCounter,mainCounter,baseCounter);

        return patternList;
    }

    /**
     * 计算 可拆除板卡形成的组合,第一个元素为整体拆除时配置
     * @param bbu
     * @return
     */
    public static List<String> calCanDismantleStringPatternList2(Bbu2 bbu){

        //格式：frame_fun_power_main_base
        int frameCounter=bbu.getFrameCounter();
        int funCounter=bbu.getFunCounter();
        int powerCounter=bbu.getPowerBoardCounter();
        int mainCounter=bbu.getControlBoardCounter();
        int baseCounter=bbu.getBaseBoardCounter();
        List<String> patternList=recycle5LoopString(baseCounter,mainCounter,powerCounter,frameCounter,funCounter);

        return patternList;
    }



    //用字符串表示pattern
    public static List<String> getBbuDividePatterns(BbuHw5g5900 bbu){

        //格式：frame_fun_power_main_base
        List<String> patternList=new ArrayList<>();
        int frameCounter=bbu.getFrameCounter();
        int funCounter=bbu.getFunCounter();
        int powerCounter=bbu.getPowerBoardCounter();
        int mainCounter=bbu.getControlBoardCounter();
        int baseCounter=bbu.getBaseBoardCounter();
        for (int i = powerCounter; i >= 0; i--) {
            for (int j = mainCounter; j >= 0; j--){
                for (int k = baseCounter; k >= 0; k--) {
                    List<Integer> intList=new ArrayList<>();
                    intList.add(frameCounter);
                    intList.add(funCounter);
                    intList.add(i);
                    intList.add(j);
                    intList.add(k);
                    String pattern=intList2String(intList);
                    patternList.add(pattern);
                }
            }
        }

        return patternList;
    }

    /**
     * 对bbuList 可插入或者可拆除 int pattern,形成list
     * @param list
     * @param isNeed 不是需要的话，就是提供的
     * @return
     */
    public static  List<IntPatternAndBbu> calIntPatternAndBbuList(List<Bbu2> list, boolean isNeed){
        List<IntPatternAndBbu> intPatternAndBbuList =new ArrayList<>();
        for (Bbu2 bbu : list) {
            List<Integer> integerList;
            if(isNeed){
                integerList= calCanInjectIntPatternList(bbu);
            }else{
                integerList= calCanDismentalIntPatternList(bbu);
            }

            for (Integer integer : integerList) {
                IntPatternAndBbu intPatternAndBbu =new IntPatternAndBbu();
                intPatternAndBbu.setIntegerIndex(integer);
                intPatternAndBbu.setBbu(bbu);
                intPatternAndBbuList.add(intPatternAndBbu);
            }
        }
        Collections.sort(intPatternAndBbuList,(bbu1, bbu2)->{
            if(bbu1.getIntegerIndex()==bbu2.getIntegerIndex()){
                return bbu1.getBbu().getNodeId()-bbu2.getBbu().getNodeId();
            }else{
                return bbu2.getIntegerIndex()-bbu1.getIntegerIndex();
            }
        });

        return intPatternAndBbuList;
    }

    /**
     * 从 拟拆除的bbuList，对所有板卡形成的组合类型：整体拆除string pattern 和 部分拆除 string pattern
     * 形成list,变成 map 返回
     * @param list
     * @return
     */
    public static  Map<String,List<StringPatternAndBbu>> calStringPatternAndBbuList(List<Bbu2> list){
        List<StringPatternAndBbu> wholePatternAndBbuList=new ArrayList<>();//整体拆除
        List<StringPatternAndBbu> partPatternAndBbuList =new ArrayList<>();//部分拆分组成的list
        for (Bbu2 bbu : list) {
            List<String> patternList;
            patternList= calCanDismantleStringPatternList2(bbu);
            for (int i = 0; i < patternList.size(); i++) {
                StringPatternAndBbu stringPatternAndBbu =new StringPatternAndBbu();
                String patternString=patternList.get(i);
                stringPatternAndBbu.setStringIndex(patternString);
                stringPatternAndBbu.setBbu(bbu);
                if(i==0 &&
                    bbu.getBaseBoardCounter()>0 &&
                    bbu.getControlBoardCounter()>0 &&
                    bbu.getPowerBoardCounter()>0 &&
                    bbu.getFunCounter()>0 &&
                    bbu.getFrameCounter() >0) {
                    wholePatternAndBbuList.add(stringPatternAndBbu);
                }else{
                    partPatternAndBbuList.add(stringPatternAndBbu);
                }
            }
        }
        Collections.sort(partPatternAndBbuList,(bbu1, bbu2)->{
            if(bbu1.getStringIndex()==bbu2.getStringIndex()){
                return bbu1.getBbu().getNodeId()-bbu2.getBbu().getNodeId();
            }else{
                return comparePatternString(bbu2.getStringIndex(),bbu1.getStringIndex());
            }
        });

        Iterator<StringPatternAndBbu> wholeIt=wholePatternAndBbuList.listIterator();
        while(wholeIt.hasNext()){
            StringPatternAndBbu current=wholeIt.next();
            if(current.getStringIndex().equals("0_0_0_0_0")){
                wholeIt.remove();
            }
        }
        Iterator<StringPatternAndBbu> partIt=partPatternAndBbuList.listIterator();
        while(partIt.hasNext()){
            StringPatternAndBbu current=partIt.next();
            if(current.getStringIndex().equals("0_0_0_0_0")){
                partIt.remove();
            }
        }


        Map<String,List<StringPatternAndBbu>> patternStringMap=new HashMap<>();
        patternStringMap.put("whole",wholePatternAndBbuList);
        patternStringMap.put("part",partPatternAndBbuList);

        return patternStringMap;
    }


    public static String intList2String(List<Integer> integerList){
        String s="";
        for (Integer integer : integerList) {
            s+=integer+"_";
        }
        s=s.substring(0,s.length()-1);
        return s;
    }

    public static List<Integer> recycle5Loop(int a,int b ,int c,int d,int e){
        List<Integer> integerList=new ArrayList<>();
        for (int i = a; i >= 0; i--) {
            for (int j = b; j >= 0; j--){
                for (int k = c; k >= 0; k--) {
                    for (int l = d; l >= 0; l--) {
                        for (int m = e; m >= 0; m--) {
                            Integer integer = i * 10000 + j * 1000 + k * 100 + l * 10 + m;
                            integerList.add(integer);
                        }
                    }
                }
            }
        }
        return integerList;
    }

    public static List<String> recycle6Loop(int a,int b ,int c,int d,int e,int f){
        List<String>  stringList=new ArrayList<>();
        for (int i = a; i >= 0; i--) {
            for (int j = b; j >= 0; j--){
                for (int k = c; k >= 0; k--) {
                    for (int l = d; l >= 0; l--) {
                        for (int m = e; m >= 0; m--) {
                            for (int n = f; n >=0 ; n--) {
                                List list=new ArrayList<>();
                                list.add(i);
                                list.add(j);
                                list.add(k);
                                list.add(l);
                                list.add(m);
                                list.add(n);
                                String s= NslUtilList.list2String(list);
                                stringList.add(s);
                            }
                        }
                    }
                }
            }
        }
        return stringList;
    }

    public static List<String> recycle5LoopString(int a,int b ,int c,int d,int e){
        List<String>  stringList=new ArrayList<>();
        for (int i = a; i >= 0; i--) {
            for (int j = b; j >= 0; j--){
                for (int k = c; k >= 0; k--) {
                    for (int l = d; l >= 0; l--) {
                        for (int m = e; m >= 0; m--) {
                            List list=new ArrayList<>();
                            list.add(i);
                            list.add(j);
                            list.add(k);
                            list.add(l);
                            list.add(m);
                            String s= NslUtilList.list2String(list);
                            stringList.add(s);
                        }
                    }
                }
            }
        }
        return stringList;

    }

    /**
     * 判断 目标bbuList,是否能够 在center room最大bbu size下整合完成 sourceList全部的bbu,如果不能的话，减少sourceList
     * 注意sourceList排序是按从近到远排序
     */
    public static List<Bbu2> filterSourceList(List<Bbu2> sourceBbuList, ApparatusRoomBo center){

        int sourceBaseCounter=0;
        int targetMaxBaseCounter=center.getBbuMaxSize()*center.getBaseSizePerBbu();

        int canInjectedMaxBaseCounter=targetMaxBaseCounter-getBaseBoardCounter(center);

        //如果机房已放置bbu 或者 base 数量 超过了规定值，仅将每个bbu剩下的slot位置保留使用，算作可以插入的基带数量
        if(canInjectedMaxBaseCounter<=0 || center.getBbuList().size()>center.getBbuMaxSize()){
            canInjectedMaxBaseCounter=0;
            for (Bbu2 bbu2 : center.getBbuList()) {
                if(bbu2.getBaseBoardCounter()<bbu2.getMaxBaseBoard()){
                    canInjectedMaxBaseCounter+=bbu2.getMaxBaseBoard()-bbu2.getBaseBoardCounter();
                }
            }
        }

        do {
            sourceBaseCounter=0;
            // 循环体，需要重复执行的代码
            for (Bbu2 bbu2 : sourceBbuList) {
                sourceBaseCounter+=bbu2.getBaseBoardCounter();
            }

            if(sourceBaseCounter>canInjectedMaxBaseCounter){
                sourceBbuList=sourceBbuList.subList(0,sourceBbuList.size()-1);

            }

        } while (sourceBaseCounter>canInjectedMaxBaseCounter);
        return sourceBbuList;
    }


    /**
     * 判断 目标bbuList,是否能够 整合完成 sourceList全部的bbu,如果不能的话，减少sourceList
     * 注意sourceList排序是按从近到远排序
     */
    public static List<Bbu2> filterSourceList(List<Bbu2> sourceBbuList, List<Bbu2> targetBbuList){
        int targetCurrentBaseCounter=0;
        int sourceBaseCounter=0;
        int targetMaxBaseCounter=0;
        for (Bbu2 bbu2 : targetBbuList) {
            targetCurrentBaseCounter+=bbu2.getBaseBoardCounter();
            targetMaxBaseCounter+=bbu2.getMaxBaseBoard();
        }

        int canInjectedMaxBaseCounter=targetMaxBaseCounter-targetCurrentBaseCounter;
        //log.info("canInjectedMaxBaseCounter = {}",canInjectedMaxBaseCounter);

        do {
            sourceBaseCounter=0;
            // 循环体，需要重复执行的代码
            for (Bbu2 bbu2 : sourceBbuList) {
                sourceBaseCounter+=bbu2.getBaseBoardCounter();
            }
            //log.info("sourceBaseCounter = {}",sourceBaseCounter);
            if(canInjectedMaxBaseCounter<=0){
                break;
            }
            //log.info("sourceBbuList.size() = {}",sourceBbuList.size());
            if(sourceBaseCounter>canInjectedMaxBaseCounter){
                sourceBbuList=sourceBbuList.subList(0,sourceBbuList.size()-1);

            }

        } while (sourceBaseCounter>canInjectedMaxBaseCounter);
        return sourceBbuList;
    }


    /**
     * 对形如4_1_1_1_1 = 4base_1main_1power_1frame_1fun_,进行比较
     * 如果 长度不一致，如4_1_1 同 3_1_1_1 比较，以最前面大的数为准，这里4_1_1靠前
     * 优先级按base,main,power来考虑，实现方式 base*100000
     * @param pattern1
     * @param pattern2
     * @return
     */
   static public int comparePatternString(String pattern1,String pattern2){
       List<Integer> list1=NslUtilList.string2IntList(pattern1,"_");
       List<Integer> list2=NslUtilList.string2IntList(pattern2,"_");
       //如果
       int size=list1.size()>list2.size()? list2.size() : list1.size();
       int result=0;
       for (int i = 0; i < size; i++) {
           if(list1.get(i)>list2.get(i)){
               result=1;
               return result;
           }else if(list1.get(i)<list2.get(i)){
               result=-1;
               return result;
           }
       }
        return list1.size()-list2.size();
    }

    /**
     * 根据机房类型，将source bbu List中直接整体搬迁至 target bbu 机房
     * 其中 sourceList 包含了 周边bbu 和 锚点机房中自整合剩下 无base的bbu
     * targetList 仅包含 锚点机房中，整合完的，包含base的bbu
     * 返回值：0为 source,1为 target
     * target中的bbu数量，就是 锚点机房最终的bbu数量，只是base、power可能为插满
     * 这也是 integrateBoard2 方法，进行的前置条件
     */
   static public List<Bbu2>[] returnWhole(List<Bbu2> sourceList,List<Bbu2> targetList,ApparatusRoomBo targetRoom){
       if(targetRoom.getId().equals("三门峡_机房_25")){
           log.info("targetRoom id = {}",targetRoom.getId());
       }

        //todo:source list 是否排序

        int baseTotal=UtilBbuReturn.getBaseBoardCounter(targetList)+UtilBbuReturn.getBaseBoardCounter(sourceList);
        Collections.sort(sourceList,(e1,e2)->{
            return e1.getBaseBoardCounter()-e2.getBaseBoardCounter();
        });
        int targetBbuSize=0;

       NslUtilPrinter.printHorizontal(" in  bug returnWhole begin");
       log.info(" source bbu list size = {}",sourceList.size());
       NslUtilPrinter.printHorizontal(" source bbu list");
       for (Bbu2 bbu2 : sourceList) {
           log.info("source bbu vendor={} , net = {}, index= {}",bbu2.getVendor(),bbu2.getNetGenerationFromBbuModel(),bbu2.getBoardStringIndex());
       }
       NslUtilPrinter.printHorizontal(" target bbu list");
       log.info(" target bbu list size = {}",targetList.size());
       for (Bbu2 bbu2 : targetList) {
           log.info("target bbu vendor={} , net = {}, index= {}",bbu2.getVendor(),bbu2.getNetGenerationFromBbuModel(),bbu2.getBoardStringIndex());
       }

       List <Bbu2> allList=new ArrayList();
       allList.addAll(sourceList);
       allList.addAll(targetList);
       String beforeString=getBoardStringIndexFromList(allList);
       log.info(" sourceList beforeString = {}",getBoardStringIndexFromList(sourceList));
       log.info(" targetList beforeString = {}",getBoardStringIndexFromList(targetList));
       log.info("beforeString = {}",beforeString);

        log.info("base Total = {}",baseTotal);


        //log.info("target base Total = {}",UtilBbuReturn.getBaseBoardCounter(targetList));

        //如果 targetRoom本身bbu list 就可以整合，直接返回
        if(targetList.size()*4>baseTotal){
            List<Bbu2>[] sourceAndTarget= new List[]{sourceList, targetList};
            return sourceAndTarget;
        }

        //如果不够，2种情况，1是超过了room 最大，2是不超过
        if(targetList.size()*4<=baseTotal){
            targetBbuSize= (int) Math.ceil(baseTotal/4.0);
        }
//        int maxSize=targetRoom.getBbuMaxSize();
//        targetBbuSize=maxSize>targetBbuSize?targetBbuSize:maxSize;

        log.info("targetBbuSize = {}",targetBbuSize);


        //需要整体 转移 回局的数量
        int needWholeReturnSize=targetBbuSize-targetList.size();

       log.info("needWholeReturnSize = {}",needWholeReturnSize);

        Map<String,List<StringPatternAndBbu>> map=calStringPatternAndBbuList(sourceList);
        List<StringPatternAndBbu> wholePattern=map.get("whole");


        if(needWholeReturnSize >= sourceList.size()){
            //log.info("in needWholeReturnSize >= sourceList.size())");
            for (Bbu2 bbu2 : sourceList) {
                bbu2.getApparatusRoomBo().getBbuList().remove(bbu2);//5_25
                targetRoom.addBbu(bbu2);//5_25
                bbu2.setApparatusRoomBo(targetRoom);
                bbu2.setApparatusRoomId(targetRoom.getId()+"");

            }
            targetList.addAll(sourceList);
            sourceList=new ArrayList<>();
        }else if(needWholeReturnSize<=wholePattern.size()){
            //log.info("in else");
            //bug?
            List<StringPatternAndBbu> toWholeReturn=wholePattern.subList(0,needWholeReturnSize);
            for (StringPatternAndBbu stringPatternAndBbu : toWholeReturn) {
                log.info("toWholeReturn stringPatternAndBbu ={} + {}",stringPatternAndBbu.getStringIndex(),stringPatternAndBbu.getBbu().getNodeId());
            }

            List<Bbu2> toWholeReturnBbuList=new ArrayList<>();
            for (StringPatternAndBbu stringPatternAndBbu : toWholeReturn) {
                Bbu2 wholeReturn=stringPatternAndBbu.getBbu();

                wholeReturn.getApparatusRoomBo().getBbuList().remove(wholeReturn);//5_25_bug
                targetRoom.addBbu(wholeReturn);//5_25

                wholeReturn.setApparatusRoomBo(targetRoom);
                wholeReturn.setApparatusRoomId(targetRoom.getId()+"");
                targetList.add(wholeReturn);
                toWholeReturnBbuList.add(wholeReturn);
            }

            log.info("toWholeReturnBbuList.size ={}",toWholeReturnBbuList.size());
            log.info(" toWholeReturnBbuList string index= {}",getBoardStringIndexFromList(toWholeReturnBbuList));
            log.info(" sourceList before remove = {}",getBoardStringIndexFromList(sourceList));
            log.info(" sourceList.size() before remove = {}",sourceList.size());



            Iterator<Bbu2> iterator=sourceList.iterator();
            while (iterator.hasNext()){
                Bbu2 bbu2=iterator.next();
                log.info("toWholeReturnBbuList.contains(bbu2) = {}",toWholeReturnBbuList.contains(bbu2));
                log.info("in remove  node id= {}",bbu2.getNodeId());
                if(bbu2.getNodeId()==982002){
                    log.info("for debug");
                }
                for (Bbu2 bbu21 : toWholeReturnBbuList) {
                    if(bbu21.getNodeId().equals(bbu2.getNodeId())){
                        iterator.remove();
                    }
                }

            }

            log.info(" sourceList after remove = {}",getBoardStringIndexFromList(sourceList));
            log.info(" sourceList.size() after remove = {}",sourceList.size());
        }

        List<Bbu2>[] sourceAndTarget= new List[]{sourceList, targetList};
        baseTotal=UtilBbuReturn.getBaseBoardCounter(targetList)+UtilBbuReturn.getBaseBoardCounter(sourceList);
       log.info("after base Total = {}",baseTotal);

       allList.clear();
       allList.addAll(sourceList);
       allList.addAll(targetList);
       String afterString=getBoardStringIndexFromList(allList);
       log.info("afterString = {}",afterString);
       if(!beforeString.equals(afterString)){
           log.info("afterString != beforeString");
           log.info("beforeString ={}  -  afterString = {}",beforeString,afterString);

       }

       log.info(" source bbu list size = {}",sourceList.size());
       log.info("targetBbuSize = {}",targetBbuSize);
       log.info(" sourceList afterString = {}",getBoardStringIndexFromList(sourceList));
       log.info(" targetList afterString = {}",getBoardStringIndexFromList(targetList));

       NslUtilPrinter.printHorizontal(" in  bug returnWhole end");
        return sourceAndTarget;
    }


    /**
     * 将source bbu，放置到目标机房中，bbu类型得是一致的，比如都是hw 5900
     * targetList 要求是最终的 bbuList,即 最终整合到这些targetList，即使其中元素为空，仅为站位。
     * 备选策略：如无法整合全部，对sourceBbu 过滤减少掉一些，先不使用
     * 退出条件2选1： 1. 所有机房的基带板，都已整合  2. 已无法匹配目标pattern
     */
    public static void integrateBoards2(List<Bbu2> sourceBbuList, List<Bbu2> targetBbuList) {
        //策略2： 确保targetBbuList能够整合全部的sourceList
//        sourceBbuList= filterSourceList(sourceBbuList,targetBbuList);
        if(sourceBbuList.size()==0){
            return;
        }

       Map<String,List<StringPatternAndBbu>> sourStringMap = UtilBbuReturn.calStringPatternAndBbuList(sourceBbuList);


       List<StringPatternAndBbu> targetStringPatternAndBbuList = UtilBbuReturn.calCanInjectStringPatternList(targetBbuList);
//        log.info("StringPatternAndBbu = {}",targetStringPatternAndBbuList);
       while(true){
           //log.info("targetStringPatternAndBbuList = {}",targetStringPatternAndBbuList);
           String stringIndex=null;
           List<StringPatternAndBbu> wholeSourceStringList=sourStringMap.get("whole");
           //log.info("wholeSourceStringList = {}",wholeSourceStringList);
           List<StringPatternAndBbu> partSourceStringList=sourStringMap.get("part");
           //log.info("partSourceStringList = {}",partSourceStringList);
           int findIndexOfWholeSourceList=-1;
           int findIndexOfPartSourceList=-1;
           List<String> wholeProvideStringIndexList= wholeSourceStringList.stream().map(intPatternAndBbu1 -> intPatternAndBbu1.getStringIndex()).collect(Collectors.toList());
           List<String> partProvideStringIndexList=partSourceStringList.stream().map(intPatternAndBbu1 -> intPatternAndBbu1.getStringIndex()).collect(Collectors.toList());


           StringPatternAndBbu currentDestinationStringPatternAndBbu =null;

           //遍历 需要的，看是否存在, 先在整体拆除整合里查找
           for (StringPatternAndBbu targetStringPatternAndBbu : targetStringPatternAndBbuList) {
               stringIndex= targetStringPatternAndBbu.getStringIndex();
               findIndexOfWholeSourceList=wholeProvideStringIndexList.indexOf(stringIndex);
               if(findIndexOfWholeSourceList!=-1){
                   currentDestinationStringPatternAndBbu = targetStringPatternAndBbu;
                   break;
               }
           }

           //遍历 需要的，看是否存在, 再在部分拆除整合里查找
           if(findIndexOfWholeSourceList==-1){
               for (StringPatternAndBbu targetStringPatternAndBbu : targetStringPatternAndBbuList) {
                   stringIndex= targetStringPatternAndBbu.getStringIndex();
                   findIndexOfPartSourceList=partProvideStringIndexList.indexOf(stringIndex);
                   if(findIndexOfPartSourceList!=-1){
                       currentDestinationStringPatternAndBbu = targetStringPatternAndBbu;
                       break;
                   }
               }
           }

           if(currentDestinationStringPatternAndBbu==null){
               break;
           }

           //找到了一个最大匹配的，target bbu add boards ,source remove boards
           if(currentDestinationStringPatternAndBbu!=null){
               StringPatternAndBbu sourceStringPatternAndBbu=null;
               if(findIndexOfWholeSourceList!=-1){
                   sourceStringPatternAndBbu=wholeSourceStringList.get(findIndexOfWholeSourceList);
               }else{
                   sourceStringPatternAndBbu=partSourceStringList.get(findIndexOfPartSourceList);
               }

               String toIntegrateStringIndex=currentDestinationStringPatternAndBbu.getStringIndex();
               Bbu2 toIntegrateTargetBbu=currentDestinationStringPatternAndBbu.getBbu();
               Bbu2 toIntegrateSourceBbu=sourceStringPatternAndBbu.getBbu();

//               log.info("before in node id ={}",toIntegrateTargetBbu.getNodeId());
//               log.info("toIntegrateTargetBbu = {}",toIntegrateTargetBbu.getBoardStringIndex());
//               log.info("toIntegrateSourceBbu = {}",toIntegrateSourceBbu.getBoardStringIndex());
//               log.info("toIntegrateStringIndex = {}",toIntegrateStringIndex);
               toIntegrateTargetBbu.integrateBoards(toIntegrateSourceBbu,toIntegrateStringIndex);
//               log.info("after in node id ={}",toIntegrateTargetBbu.getNodeId());
//               log.info("toIntegrateTargetBbu = {}",toIntegrateTargetBbu.getBoardStringIndex());
//               log.info("toIntegrateSourceBbu = {}",toIntegrateSourceBbu.getBoardStringIndex());
//               log.info("toIntegrateStringIndex = {}",toIntegrateStringIndex);
               //baseCounterSum


               //更新状态
               sourStringMap = UtilBbuReturn.calStringPatternAndBbuList(sourceBbuList);
               targetStringPatternAndBbuList = UtilBbuReturn.calCanInjectStringPatternList(targetBbuList);
           }
           int leftBaseCounter=0;
           for (Bbu2 bbu2 : sourceBbuList) {
               //log.info("bbu2.getPowerBoardCounter() = {}",bbu2.getPowerBoardCounter());
               //log.info("bbu2.getBaseBoardCounter() = {}",bbu2.getBaseBoardCounter());
               leftBaseCounter+=bbu2.getBaseBoardCounter();
           }
           //log.info("leftBaseCounter = {}",leftBaseCounter);
           if(leftBaseCounter==0){
               break;
           }
       }
    }

    static public int getBaseBoardCounter(List<Bbu2> bbu2List){
        int sum=0;
        for (Bbu2 bbu2 : bbu2List) {
            sum+=bbu2.getBaseBoardCounter();
        }
        return sum;
    }

    static public int getBaseBoardCounter(ApparatusRoomBo roomBo){
        return getBaseBoardCounter(roomBo.getBbuList());
    }

    static public int getBaseBoardCounterOfApparatusRoomBoList(List<ApparatusRoomBo> roomBoList){
        int sum=0;
        for (ApparatusRoomBo roomBo : roomBoList) {
            sum+=getBaseBoardCounter(roomBo);
        }
        return sum;
    }

    static public List<Bbu2> getBbuListFromApparatusRoomBoList(List<ApparatusRoomBo> roomBoList){
        List<Bbu2> bbu2List=new ArrayList<>();
        for (ApparatusRoomBo roomBo : roomBoList) {
            bbu2List.addAll(roomBo.getBbuList());
        }
        return bbu2List;
    }

    static  public String getBoardStringIndexFromList(List<Bbu2> bbu2List){
        int frameCounter=0;
        int funCounter=0;
        int baseCounter=0;
        int controlCounter=0;
        int powerCounter=0;
        for (Bbu2 bbu2 : bbu2List) {
            frameCounter+=bbu2.getFrameCounter();
            funCounter+=bbu2.getFunCounter();
            baseCounter+=bbu2.getBaseBoardCounter();
            controlCounter+=bbu2.getControlBoardCounter();
            powerCounter+=bbu2.getPowerBoardCounter();
        }
        return baseCounter+"_"+controlCounter+"_"+powerCounter+"_"+frameCounter+"_"+funCounter;
    }

}
